/*
 * DynamicArithmeticDescompresor.cpp
 *
 *  Created on: 01/12/2009
 *      Author: hernan
 */

#include "DynamicArithmeticDescompresor.h"

DynamicArithmeticDescompresor::DynamicArithmeticDescompresor() {


	this->contextTable =  new ContextTable(256);

}

DynamicArithmeticDescompresor::~DynamicArithmeticDescompresor() {
	delete this->contextTable;
}


string DynamicArithmeticDescompresor::doUncompress(){


	string cadenaDescomprimida;

	char contexto = 'A';

	this->getBitManager().setCompressString(this->stringToUncompress);

	int posicion;

	posicion = this->getBitManager().getIntToDescompress();

	unsigned int cero = 0;

	unsigned int max = cero - (+1);

	cout << "MAX: " << max << endl;

	this->setRoof(max);

	this->setFloor(0);

	char caracterDescomprimido;

	while (posicion != -1){

		double length = CompresorUtil::calculateLength(this->getFloor(), this->getRoof());

		double acumulatedProbability = CompresorUtil::calculateAcummulateProbability(length,posicion); // Calcula la probabilidad acumulada tomando como techo a la posicion

		caracterDescomprimido = this->getContextTable()->getCharByAcummulatedProbability(acumulatedProbability,contexto); //Calcula el probabilidad acumulada mayor o igual a la obtenida

		int caracterInt = static_cast <int> (caracterDescomprimido);

		caracterInt =  caracterInt - 1;

		char caracterAnterior = static_cast <char> (caracterInt);

		double probability = this->getContextTable()->getAcummulatedProbability(caracterAnterior,contexto); //Obtiene la probabilidad del caracter anterior al obtenido

		int techo = CompresorUtil::calculateNewRoof(probability,length);

		this->setFloor(CompresorUtil::calculateNewFloor(techo)); // El techo obtenido pasa a ser el piso del caracter obtenido

		probability = this->getContextTable()->getAcummulatedProbability(caracterDescomprimido,contexto); // Se calcula el techo del caracter obtenido

		this->setRoof(CompresorUtil::calculateNewRoof(probability,length)); // Se calcula el techo del caracter obtenido


		this->getContextTable()->updateTable(contexto,caracterDescomprimido); // Se actualiza tabla de contextos

		contexto = caracterDescomprimido;

		cadenaDescomprimida.push_back(caracterDescomprimido);

		this->getBitManager().normalize(this->getFloor(),this->getRoof());

		this->setFloor(this->getBitManager().getNormalizedFloor()); // Se normalizan piso y techo

		this->setRoof(this->getBitManager().getNormalizedRoof());

		posicion = this->getBitManager().getIntToDescompress(); // Se obtiene el proximo entero

	}

	return cadenaDescomprimida;


}

unsigned int DynamicArithmeticDescompresor::getFloor() const{

	return this->floor;

}

unsigned int DynamicArithmeticDescompresor::getRoof() const{

	return this->roof;

}

void DynamicArithmeticDescompresor::setFloor(unsigned int floor){

	this->floor = floor;

}

void DynamicArithmeticDescompresor::setRoof(unsigned int roof){

	this->roof = roof;

}

ContextTable* DynamicArithmeticDescompresor::getContextTable() const{

	return this->contextTable;

}

void DynamicArithmeticDescompresor::setBitManager(BitManager bitManager){

	this->bitManager = bitManager;

}

BitManager DynamicArithmeticDescompresor::getBitManager() const{

	return this->bitManager;

}

string DynamicArithmeticDescompresor::getStringToUncompress() const{

	return this->stringToUncompress;

}

void DynamicArithmeticDescompresor::setStringToUncompress(string stringToUncompress){

	this->stringToUncompress = stringToUncompress;

}


